//////////////////////////////////////////////////
// Common.h
//
// Author: Tarik Belabbas et Adrien Hoffer
//////////////////////////////////////////////////

#ifndef COMMON_H_
#define COMMON_H_

#include <QDebug>
#include <QCoreApplication>

#define ST_ERROR_BUFFER_SIZE 2048

#define ST_DECLARE_SINGLETON( _class )										\
	private:																\
	static _class* s_instance;												\
	public:																	\
	static void		s_create		();										\
	static void		s_destroy		();										\
	static _class*	s_getInstance	()	{ return s_instance; }

#define ST_SINGLETON_INIT( _class )											\
	_class* _class::s_instance = NULL;										\
	void	_class::s_create	()	{ s_instance = new _class; }			\
	void	_class::s_destroy	()	{ delete s_instance; s_instance = NULL; }

#define ST_SPRINTF					sprintf
#define ST_SNPRINTF					snprintf
#define ST_VSPRINTF					vsprintf
#define ST_VSNPRINTF				vsnprintf
#define ST_EXIT()					QCoreApplication::exit()

enum stEErrorType
{
	stEErrorType_LOG,
	stEErrorType_LOG_GAME,
	stEErrorType_WARNING,
	stEErrorType_ASSERT,
	stEErrorType_ERROR
};

///---------------------------------------------------------
class stErrorInfo
{
public:
	stErrorInfo( stEErrorType _type, const char* _file, const unsigned int _line, const char* _func, const char* _expr)
		: m_type(_type), m_file(_file), m_line(_line), m_func(_func), m_expr(_expr) { m_message[0] = 0; }
	~stErrorInfo() {}

	void			setMessage( const char* _format, ...);
	void			setMessage( const char* _format, va_list _argList);

	stEErrorType	getType() const		{ return m_type; }
	const char*		getFile() const		{ return m_file; }
	unsigned int	getLine() const		{ return m_line; }
	const char*		getFunc() const		{ return m_func; }
	const char*		getExpr() const		{ return m_expr; }
	const char*		getMessage() const	{ return m_message; }

private:

	stEErrorType	m_type;
	const char*		m_file;
	unsigned int	m_line;
	const char*		m_func;
	const char*		m_expr;
	char			m_message[ ST_ERROR_BUFFER_SIZE];

};

const char*	formatErrorMessage( const char* _format, ... );

void		errorMsg( stEErrorType _errorT, const char* _file,
		const unsigned int _line, const char* _func, const char* _expr,
		const char* _msg, bool& _cancel);

///---------------------------------------------------------
bool	callAssert	( const stErrorInfo& _error );
bool	callError	( const stErrorInfo& _error );
int		messageBox	( const stErrorInfo& _error );

#define ST_ERROR( _msg ) \
{\
	static bool once##__FILE__##__LINE__ = true;\
	if (once##__FILE__##__LINE__) {\
		const char* __errortemp__ = formatErrorMessage _msg;\
		errorMsg( stEErrorType_ERROR, __FILE__, __LINE__, __FUNCTION__, NULL, __errortemp__, once##__FILE__##__LINE__);\
	}\
}

#define ST_LOG( _msg ) \
{\
	const char* __logtemp__ = formatErrorMessage _msg;\
	bool dummy;\
	errorMsg( stEErrorType_LOG, __FILE__, __LINE__, __FUNCTION__, NULL, __logtemp__, dummy );\
}

#ifndef QT_NO_DEBUG

#define ST_ASSERT( _expr, _msg ) \
{\
	if (!(_expr))\
	{\
		static bool once##__FILE__##__LINE__ = true;\
		if (once##__FILE__##__LINE__) {\
			const char* __errortemp__ = formatErrorMessage _msg;\
			errorMsg( stEErrorType_ASSERT,__FILE__, __LINE__, __FUNCTION__, #_expr, __errortemp__, once##__FILE__##__LINE__);\
		}\
	}\
}

#define ST_WARNING( _msg ) \
{\
	const char* __errortemp__ = formatErrorMessage( _msg );\
	bool dummy;\
	errorMsg( stEErrorType_WARNING, __FILE__, __LINE__, __FUNCTION__, NULL, __errortemp__, dummy);\
}

#else // DEBUG

#define ST_ASSERT( _expr, _msg )	{}
#define ST_WARNING( _msg )			{}

#endif // DEBUG

#endif /* COMMON_H_ */
